#include <iostream>
#include <cassert>
#include <cstdlib>
#include <cstring>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

using namespace std;

int main()
{
    // 1、创建匿名管道
    int pipefd[2]; // 数组
    int ret = pipe(pipefd);
    assert(ret == 0);
    (void)ret; // 防止 release 模式中报警告

    // 2、创建子进程
    pid_t id = fork();
    if (id == 0)
    {
        // 子进程内
        close(pipefd[0]); // 3、子进程关闭写端

        // 4、开始通信

        // // 父进程不写（空），子进程读
        // int cnt = 1;
        // while (true)
        // {
        //     char ch;
        //     read(pipefd[0], &ch, 1);
        //     cout << "已读取 " << cnt++ << " 字节的数据" << endl;
        // }

        // // 父进程写（满），子进程不读
        // while (true)
        // {
        // }

        while (true)
        {
            char buff[] = "Hello pipe!";
            write(pipefd[1], buff, strlen(buff)); // 写入数据
            sleep(1);
        }

        close(pipefd[1]); // 关闭剩下的读端
        exit(0);          // 子进程退出
    }

    // 父进程内
    close(pipefd[1]); // 3、父进程关闭读端

    // 4、开始通信

    // // 父进程不写（空），子进程读
    // while (true)
    // {
    // }

    // //父进程写（满），子进程不读
    // int cnt = 1; // 计数器
    // while (true)
    // {
    //     char ch = 'x';
    //     write(pipefd[1], &ch, 1); // 写入数据
    //     cout << "已写入 " << cnt++ << " 字节的数据" << endl;
    // }

    // char buff[] = "Hello pipe!";
    // write(pipefd[1], buff, strlen(buff)); // 写入数据

    // close(pipefd[1]); // 关闭剩下的写端

    char buff[64];
    int cnt = 1;
    while (true)
    {
        int n = read(pipefd[0], buff, sizeof(buff) - 1);
        buff[n] = '\0';

        if (n == 0)
            cout << "写端已关闭，读取数据量为: " << n << " 字节" << endl;
        else
            cout << "成功读取到信息: " << buff << endl;

        // 读取五次后，关闭读端
        if (cnt++ == 5)
            break;
    }

    close(pipefd[0]);

    // 父进程等待子进程结束
    int status = 0;
    waitpid(id, &status, 0);
    printf("子进程异常退出，core dump: %d   退出信号：%d\n", (status >> 7) & 1, (status & 0x7F));
    return 0;
}

// int main()
// {
//     // 1、创建匿名管道
//     int pipefd[2]; // 数组
//     int ret = pipe(pipefd);
//     assert(ret == 0);
//     (void)ret; // 防止 release 模式中报警告

//     // 2、创建子进程
//     pid_t id = fork();
//     if (id == 0)
//     {
//         // 子进程内
//         close(pipefd[1]); // 3、子进程关闭写端

//         // 4、开始通信
//         char buff[64]; // 缓冲区
//         while (true)
//         {
//             int n = read(pipefd[0], buff, sizeof(buff) - 1);    //注意预留一个位置存储 '\0'
//             buff[n] = '\0';

//             if (n >= 5 && n < 64)
//             {
//                 // 读取到了信息
//                 cout << "子进程成功读取到信息：" << buff << endl;
//             }
//             else
//             {
//                 // 未读取到信息
//                 if (n == 0)
//                     cout << "子进程没有读取到信息，通信结束！" << endl;
//                 // 读取异常（消息过短）
//                 else
//                     cout << "子进程读取数据量为：" << n << " 消息过短，通信结束！" << endl;
//                 break;
//             }
//         }

//         close(pipefd[0]); // 关闭剩下的读端
//         exit(0);          // 子进程退出
//     }

//     // 父进程内
//     close(pipefd[0]); // 3、父进程关闭读端

//     char buff[64];

//     // 4、开始通信
//     srand((size_t)time(NULL)); // 随机数种子
//     while (true)
//     {
//         int n = rand() % 26;
//         for (int i = 0; i < n; i++)
//             buff[i] = (rand() % 26) + 'A'; // 形成随机消息
//         buff[n] = '\0';                    // 结束标志

//         cout << "=============================" << endl;
//         cout << "父进程想对子进程说: " << buff << endl;
//         write(pipefd[1], buff, strlen(buff)); // 写入数据

//         if (n < 5)
//             break; // 消息过短时，不写入

//         sleep(1);
//     }

//     close(pipefd[1]); // 关闭剩下的写端

//     // 父进程等待子进程结束
//     int status = 0;
//     waitpid(id, &status, 0);

//     // 通过 status 判断子进程运行情况
//     if ((status & 0x7F))
//     {
//         printf("子进程异常退出，core dump: %d   退出信号：%d\n", (status >> 7) & 1, (status & 0x7F));
//     }
//     else
//     {
//         printf("子进程正常退出，退出码：%d\n", (status >> 8) & 0xFF);
//     }

//     return 0;
// }